/**
 * 2017，thor.com，all rights reserved。
 * 
 * Project：		palmmall-core
 * Filename：	SalesRptDaoImpl.java
 * Created：		2017年4月27日
 * Creator：		wolv
 */
package com.thor.palmmall.dao.rpt.sales;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.thor.commons.exception.ThorServiceException;
import com.thor.commons.util.Assert;
import com.thor.commons.util.StringUtil;
import com.thor.dao.BasicDao;
import com.thor.palmmall.api.rpt.Report;
import com.thor.palmmall.api.rpt.sales.DailySalesReportParam;
import com.thor.trans.ThorTX;

/**
 * @author wolv
 *
 */
@Transactional(rollbackFor = Exception.class, propagation = Propagation.NOT_SUPPORTED)
public class SalesRptDaoImpl extends BasicDao implements SalesRptDao {

  @Override
  @SuppressWarnings("unchecked")
  public Report calcDailyReport(DailySalesReportParam param) throws ThorServiceException {
    Assert.assertArgumentNotNull(param, "param");

    param.validate();

    Query query = DailySalesReportHqlBuilder.getInstance().build(param);
    List<Object[]> rawReports = query.getResultList();

    return Report.readFrom(rawReports);
  }

  @Override
  public Report calcDailySalesReport(DailySalesReportParam param) throws ThorServiceException {

    Assert.assertArgumentNotNull(param, "param");

    param.validate();

    Query query = SalesReportSqlBuilder.getInstance().buildDailySalesReportSql(param);
    List<Object[]> rawReports = query.getResultList();

    return Report.readFrom(rawReports);
  }

  @Override
  public Report calcMonthSalesReport(DailySalesReportParam param) throws ThorServiceException {
    Assert.assertArgumentNotNull(param, "param");

    param.validate();

    Query query = SalesReportSqlBuilder.getInstance().buildMonthSalesReportSql(param);
    List<Object[]> rawReports = query.getResultList();

    return Report.readFrom(rawReports);
  }

  @Override
  public Date getEarliestReportByStoreId(String storeId) {
    Assert.assertArgumentNotNull(storeId, "storeId");
    Query query = em.createQuery(
        "select min(date) from " + PDailySales.class.getName() + " where storeId = :storeId");
    query.setParameter("storeId", storeId);
    if (query.getResultList() == null || query.getResultList().isEmpty()) {
      return null;
    }
    return (Date) query.getResultList().get(0);
  }

  @Override
  public Date getLastestReportByStoreId(String storeId) {
    Assert.assertArgumentNotNull(storeId, "storeId");
    Query query = em.createQuery(
        "select max(date) from " + PMonthSalesReport.class.getName() + " where storeId = :storeId");
    query.setParameter("storeId", storeId);
    if (query.getResultList() == null || query.getResultList().isEmpty()) {
      return null;
    }
    return (Date) query.getResultList().get(0);
  }

  @Override
  @ThorTX
  public void saveSalesReport(PMonthSalesReport report) {
    em.persist(report);
  }

  @Override
  public List<String> queryAllStoreIds() {
    Query query = em.createQuery("select distinct(storeId) from " + PDailySales.class.getName());
    if (query.getResultList() == null || query.getResultList().isEmpty()) {
      return new ArrayList<String>();
    }
    return query.getResultList();
  }

  @Override
  public List<PMonthSalesReport> queryMonthReport(DailySalesReportParam param) {
    StringBuffer sb = new StringBuffer();
    sb.append("select date,sum(amount) as amount,storeId from " + PMonthSalesReport.class.getName()
        + " as pd where 1=1");
    if (StringUtil.isNullOrBlank(param.getStoreId()) == false)
      sb.append(" and storeId = :storeId");
    if (param.getBeginDate() != null)
      sb.append(" and date >= :beginDate");
    if (param.getEndDate() != null)
      sb.append(" and date <= :endDate");
    sb.append(" group by date order by date asc");

    Query query = em.createQuery(sb.toString());
    if (StringUtil.isNullOrBlank(param.getStoreId()) == false)
      query.setParameter("storeId", param.getStoreId());
    if (param.getBeginDate() != null)
      query.setParameter("beginDate", param.getBeginDate());
    if (param.getEndDate() != null)
      query.setParameter("endDate", param.getEndDate());
    List<Object[]> rawReports = query.getResultList();
    List<PMonthSalesReport> mthReport = new ArrayList<PMonthSalesReport>();
    for (Object[] rawReport : rawReports) {
      PMonthSalesReport item = new PMonthSalesReport();
      mthReport.add(item);
      if (rawReport.length >= 1) {
        try {
          item.setDate(new Date(((Timestamp)rawReport[0]).getTime()));
        } catch (Exception e) {
          e.printStackTrace();
        }

      }
      if (rawReport.length >= 2) {
        item.setAmount(
            rawReport[1] == null ? BigDecimal.ZERO : new BigDecimal(rawReport[1].toString()));
      }

      if (rawReport.length >= 3) {
        item.setStoreId(StringUtil.toString(rawReport[2]));
      }
    }
    return mthReport;
  }

  @PersistenceContext(unitName = "${thor-webui-core.persistent-unit}")
  protected EntityManager em;

  @Override
  public List<PMonthSalesReport> querySalesReportByMonth(DailySalesReportParam param) {
    StringBuffer sb = new StringBuffer();
    // select
    sb.append("select pd from " + PMonthSalesReport.class.getName() + " as pd where 1=1");
    if (StringUtil.isNullOrBlank(param.getStoreId()) == false)
      sb.append(" and storeId = :storeId");
    if (param.getDate() != null)
      sb.append(" and date = :date");
    sb.append(" group by floor order by floor asc");
    Query query = em.createQuery(sb.toString());
    if (StringUtil.isNullOrBlank(param.getStoreId()) == false)
      query.setParameter("storeId", param.getStoreId());
    if (param.getDate() != null)
      query.setParameter("date", param.getDate());
    return query.getResultList();
  }

  @Override
  public Report calcFloorMonthSalesReport(DailySalesReportParam param) {
    Assert.assertArgumentNotNull(param, "param");
    Query query = SalesReportSqlBuilder.getInstance().buildMonthFloorReportSql(param);
    List<Object[]> rawReports = query.getResultList();
    return Report.readFrom(rawReports);
  }
}
